// config
import { tableColumnAlign, tableColumnMixWidth } from '../config'

// eslint-disable-next-line no-unused-vars
import { Column } from 'vxe-table'

// cell render opts
import { options as tagRenderOpts } from '../render/cellRender/tag'
import { options as flagTagRenderOpts } from '../render/cellRender/flagtag'
import { options as imageRenderOpts } from '../render/cellRender/image'
import { options as iconRenderOpts } from '../render/cellRender/icon'
import { options as linkRenderOpts } from '../render/cellRender/link'
import { options as nickNameRenderOpts } from '../render/cellRender/nickname'
import { options as dropDownMenuRenderOpts } from '../render/cellRender/dropDownMenu'
import { options as priceCellRenderOpts } from '../render/cellRender/price'
import { options as uploadRenderOpts } from '../render/cellRender/upload'
import { options as timeFromRenderOpts } from '../render/cellRender/timeFrom'
import { options as progressRenderOpts } from '../render/cellRender/progress'
import { options as switchRenderOpts } from '../render/cellRender/switch'
import { options as storeNameRenderOpts } from '../render/cellRender/storeName'
import { options as normalRenderOpts } from '../render/cellRender/normal'

// editable render opts
import { options as dateRenderOpts } from '../render/editRender/date'
import { options as dateTimeRenderOpts } from '../render/editRender/dateTime'
import { options as inputRenderOpts } from '../render/editRender/input'
import { options as numberRenderOpts } from '../render/editRender/number'
import { options as selectRenderOpts } from '../render/editRender/select'
import { options as textareaRenderOpts } from '../render/editRender/textarea'
import { options as priceEditRenderOpts } from '../render/editRender/price'

// utils
import _cloneDeep from 'lodash/cloneDeep'
import isFunction from 'lodash/isFunction'
import { getAttrs, getSlot } from '../utils'
import localStore from '@Components/assets/js/utils/localStore'
import { tableNamespace } from '../config'
import createBem from '@Components/assets/js/utils/bem'
const bem = createBem(tableNamespace)

/** @param column { Column } */
const mergeCellRenderOpts = column => {
  if (column.type) return
  switch (column.cellRender?.name) {
    case 'Tag':
      Object.assign(column, tagRenderOpts)
      break
    case 'FlagTag':
      Object.assign(column, flagTagRenderOpts)
      break
    case 'Image':
      Object.assign(column, imageRenderOpts)
      break
    case 'Icon':
      Object.assign(column, iconRenderOpts)
      break
    case 'Link':
      Object.assign(column, linkRenderOpts)
      break
    case 'NickName':
      Object.assign(column, nickNameRenderOpts)
      break
    case 'DropDownMenu':
      Object.assign(column, dropDownMenuRenderOpts)
      break
    case 'Price':
      Object.assign(column, priceCellRenderOpts)
      break
    case 'Upload':
      Object.assign(column, uploadRenderOpts)
      break
    case 'TimeFrom':
      Object.assign(column, timeFromRenderOpts)
      break
    case 'Progress':
      Object.assign(column, progressRenderOpts)
      break
    case 'Switch':
      Object.assign(column, switchRenderOpts)
      break
    case 'StoreName':
      Object.assign(column, storeNameRenderOpts)
      break
    case 'Normal':
      Object.assign(column, normalRenderOpts)
      break
  }
}

/** @param column { Column } */
const mergeEditRenderOpts = column => {
  if (column.type) return
  switch (column.editRender?.name) {
    case 'Date':
      Object.assign(column, dateRenderOpts)
      break
    case 'DateTime':
      Object.assign(column, dateTimeRenderOpts)
      break
    case 'Input':
      Object.assign(column, inputRenderOpts)
      break
    case 'Number':
      Object.assign(column, numberRenderOpts)
      break
    case 'Select':
      Object.assign(column, selectRenderOpts)
      break
    case 'Textarea':
      Object.assign(column, textareaRenderOpts)
      break
    case 'Price':
      Object.assign(column, priceEditRenderOpts)
      break
  }
}

/**
 * 根据 filterRender.name 属性设置 filters
 * @param column { Column }
 * */
function setColumnFilters(column) {
  const filterRender = column.filterRender
  let filters
  switch (filterRender.name) {
    case 'String':
    case 'Number':
      filters = [{ data: { value: '', filterType: 'eq' } }]
      break
    case 'Select':
      filters = filterRender?.options?.multiple
        ? [{ data: [] }]
        : [{ data: '' }]
      break
    case 'Date':
      filters = [{ data: [] }]
      break
    case 'DateTime':
      filters = [{ data: [] }]
      break
    default:
      filters = []
  }
  column.filters = filters
}

/**
 * 可编辑表格添加类名
 *  @param column {Column}
 * @param editConfig {import('vxe-table').EditConfig}
 *  */
const addEditableCellClassName = column => {
  const className = column.className
  const enabled = column.editRender.enabled !== false

  column.className = params => {
    const classNameList = []
    if (typeof className === 'string') {
      classNameList.push(className)
    } else if (typeof className === 'function') {
      classNameList.push(className(params))
    }
    if (enabled) {
      const disabled = column?.editRender?.options?.disabled
      const _disabled = isFunction(disabled) ? disabled(params) : disabled
      if (!_disabled) {
        classNameList.push(`${bem('table')}__editableColumn`)
      }
    }

    return classNameList.join(' ')
  }
}

/**
 *
 * @param {Column} column
 */
const setColumnFormatter = column => {
  const { formatter, editRender, cellRender } = column
  const anyRender = editRender || cellRender
  if (formatter && anyRender) {
    anyRender.formatter = formatter
    column.formatter = undefined
  }
}

export default {
  props: {
    /**
     * @type {Array<Column>}
     */
    columns: {
      type: Array,
      default() {
        return []
      }
    },
    // 选择框选择方式 checkbox：允许多选，radio：只允许单选，null：关闭选择
    selectionType: {
      type: String,
      default: 'checkbox',
      validator: value => {
        return ['checkbox', 'radio', null].includes(value)
      }
    },
    // 操作栏宽度
    toolWidth: {
      type: Number
    },
    // 操作栏固定侧
    toolFixed: {
      type: String
    },
    // 操作栏权限
    toolPermission: {
      type: String
    },
    // 权限码
    permission: {
      type: String
    }
  },
  data() {
    return {
      initd: false,
      tableColumns: [],
      // 权限列表
      permissionList: localStore.getUserPermission(),
      // `editConfig.trigger` 为 'single' 和 editClosed 里面的请求还没结束时，阻止激活下一个编辑单元格
      singleEditLoading: false
    }
  },
  watch: {
    columns: {
      handler: '$handleColumns',
      deep: true,
      immediate: true
    }
  },
  computed: {
    loading() {
      const loading = getAttrs(this, 'loading')
      if (loading !== undefined) {
        return loading
      }
      return this.singleEditLoading
    },
    /** @returns {import('vxe-table').EditConfig} */
    editConfig() {
      let activeMethod = () => true
      const _editConfig = getAttrs(this, 'editConfig')
      if (_editConfig?.activeMethod) {
        activeMethod = _editConfig.activeMethod
      }

      let trigger = 'click'
      // trigger 不等于 undefined 和 trigger 不等于 'single'
      if (_editConfig?.trigger && _editConfig.trigger !== 'single') {
        trigger = _editConfig.trigger
      }
      return {
        mode: 'cell',
        ..._editConfig,
        trigger,
        activeMethod: params => {
          const { column, $table } = params
          if (
            _editConfig?.trigger === 'single' &&
            ($table.editStore.actived.row || this.singleEditLoading)
          ) {
            !this.singleEditLoading && this._clearActived()
            return false
          }
          return (
            activeMethod(params) &&
            this.checkPermission(`${column.property}_edit`)
          )
        }
      }
    }
  },
  methods: {
    /** @param columns { Array<Column> } */
    $handleColumns(columns) {
      /** @type  { Array<Column> } */
      let buildInColumns = []
      if (!this.initd) {
        this.initd = true
        buildInColumns = this.handleBuildInColumns()
      }
      const tableColumns = _cloneDeep(columns).map(column => {
        const anyRender = column.editRender || column.cellRender
        if (anyRender && !anyRender.options) {
          anyRender.options = {}
        }
        if (!anyRender) {
          column.cellRender = {
            name: 'Normal'
          }
        }

        if (column.cellRender) {
          column.cellRender['$tableInstance'] = this
          mergeCellRenderOpts(column)
        }
        if (column.editRender) {
          column.editRender['$tableInstance'] = this
          const editConfig = getAttrs(this, 'editConfig')
          const noPermission = !this.checkPermission(`${column.field}_edit`)
          if (noPermission) {
            column.editRender.options = {
              ...column.editRender.options,
              disabled: noPermission
            }
          } else {
            column.editRender.options = {
              disabled: editConfig?.disableMethod,
              ...column.editRender.options
            }
          }
          addEditableCellClassName(column)
          mergeEditRenderOpts(column)
        }
        if (column.filterRender) {
          column.filterRender['$tableInstance'] = this
          setColumnFilters(column)
        }

        //默认 formatter
        setColumnFormatter(column)

        //默认最小宽度
        column.minWidth ?? (column.minWidth = tableColumnMixWidth)
        //默认对齐
        column.align ?? (column.align = tableColumnAlign)

        return column
      })
      let mergeColumns = [...buildInColumns, ...tableColumns]
      // 权限控制

      if (this.permission) {
        mergeColumns = mergeColumns.filter(i => !i.permission || !this.checkPermission(i.permission))
      }
      this.tableColumns = mergeColumns
    },
    handleBuildInColumns() {
      const columns = []
      /** @type  { Column } } */
      const seqColumn = {
        type: 'seq',
        field: '_seq',
        title: '序',
        fixed: 'left',
        headerAlign: 'center',
        align: 'center',
        resizable: false,
        width: 50,
        slots: {
          header: (_, h) => {
            return [
              h('el-button', {
                props: { icon: 'el-icon-s-tools', type: 'text' },
                on: {
                  click: () => this.handleOpenColumnSetting()
                }
              })
            ]
          }
        }
      }
      columns.push(seqColumn)

      if (this.selectionType !== null) {
        /** @type  { Column } } */
        const selectColumn = {
          type: this.selectionType,
          field: '_select',
          fixed: 'left',
          headerAlign: 'center',
          align: 'center',
          resizable: false,
          width: 50
        }
        columns.push(selectColumn)
      }

      if (getAttrs(this, 'treeConfig')?.children) {
        /** @type  { Column } } */
        const treeColumn = {
          treeNode: true,
          width: 50,
          title: '展开',
          field: '_expand',
          resizable: false,
          showOverflow: false,
          headerAlign: 'center',
          align: 'center',
        }
        columns.push(treeColumn)
      }

      const contentSlot = getSlot(this, 'content')
      if (contentSlot) {
        /** @type  { Column } } */
        const expendSlotColumn = {
          width: 50,
          title: '展开',
          field: '_expand',
          type: 'expand',
          resizable: false,
          headerAlign: 'center',
          align: 'center',
          slots: {
            content: contentSlot
          }
        }
        columns.push(expendSlotColumn)
      }

      const toolSlot = getSlot(this, 'tool')
      if (toolSlot && !this.$store.getters.navigator) {
        const toolHeaderSlot = getSlot(this, 'toolHeader')
        /** @type  { Column } } */
        const toolSlotColumn = {
          width: this.toolWidth || tableColumnMixWidth,
          title: '操作',
          field: '_tool',
          headerAlign: 'center',
          align: 'center',
          slots: {
            default: toolSlot
          }
        }
        if (this.toolFixed) {
          toolSlotColumn['fixed'] = this.toolFixed
        }
        if (this.toolPermission) {
          toolSlotColumn['permission'] = this.toolPermission
        }
        toolHeaderSlot && (toolSlotColumn.slots.header = toolHeaderSlot)
        columns.push(toolSlotColumn)
      }
      return columns
    },
    /** @param field {string} */
    checkPermission(field) {
      return !this.$store.getters.permissions.includes(
        `${this.permission}:${field}`
      )
    }
  }
}
